// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-8-26

#ifndef __SOCKTOOL_H_COMMON_BASE__
#define __SOCKTOOL_H_COMMON_BASE__

#pragma once

#include "thread.h"
#include "singlelist.h"

class CJoySockBase;
class CJoySockData;
class CJoySockRecvData;

//##ModelId=44CF17560213
enum SOCK_ASY_MESSAGE
{
	//##ModelId=44CF17560215
    SAM_BASE = WM_USER+0x39,
	//##ModelId=44CF17560216
    SAM_RECV_DATA,
	//##ModelId=44CF17560217
    SAM_CLOSE_SOCK,
	//##ModelId=44CF17560222
    SAM_CONNECTED,
	//##ModelId=44CF17560223
    SAM_ACCEPT,
};

//##ModelId=44CF17560224
class CJoySockConnect
{
public:
	//##ModelId=44CF17560233
    CJoySockData*   m_data;
	//##ModelId=44CF17560238
    sockaddr_in     m_addr;
};
/*
class CJoySockAccept
{
public:
    CJoySockData*   m_data;
    void*   m_callerData;
    int     m_callerDataSize;
    CJoySockAccept()
    {
        memset(this, 0, sizeof(CJoySockAccept));
    }
    ~CJoySockAccept()
    {
        if(m_callerData != NULL)
        {
            delete m_callerData;
        }
    }
};
*/
//##ModelId=44CF17560261
class CJoySocketTool
{
public:
    // types.
	//##ModelId=44CF17570034
    typedef CMap<SOCKET, SOCKET, CJoySockBase*, CJoySockBase*> CSockMap;
	//##ModelId=44CF1757003F
    class CThreadData
    {
    public:
		//##ModelId=44CF17570040
        HANDLE  m_hThread;
		//##ModelId=44CF17570041
        DWORD   m_dwThreadId;
		//##ModelId=44CF17570042
        CThreadData()
            : m_hThread(NULL), m_dwThreadId(0)
        {
        }
    };
	//##ModelId=44CF1757004E
    struct CClearThread
    {
		//##ModelId=44CF17570050
        HANDLE  m_hThread;
		//##ModelId=44CF17570051
        HANDLE  m_hEvent;
		//##ModelId=44CF17570052
        DWORD   m_dwWaitTime;
		//##ModelId=44CF17570053
        CList<HANDLE>   m_threads;
		//##ModelId=44CF1757005E
        CJoyCriticalSection m_lock;

		//##ModelId=44CF17570062
        int PeekThreads(HANDLE* pHandle, int c);
    };

    // datas.
	//##ModelId=44CF17560271
    volatile    bool m_shutdown;
	//##ModelId=44CF17560272
    DWORD       m_timeOut;
	//##ModelId=44CF17560274
    CSockMap    m_socks;
	//##ModelId=44CF17560279
    CJoyCriticalSection m_lock;

	//##ModelId=44CF17560282
    HWND        m_hAsyWnd;

	//##ModelId=44CF17560284
    CClearThread    m_clearThread;

	//##ModelId=44CF17560288
    CJoySocketTool();
	//##ModelId=44CF1756029F
    ~CJoySocketTool();

    // clear threads.
	//##ModelId=44CF175602AF
    DWORD ClearThreadProc(void*);
	//##ModelId=44CF175602BF
    static DWORD WINAPI sClearThreadProc(void* pContext);
	//##ModelId=44CF175602CE
    bool CreateClearThread();
	//##ModelId=44CF175602DE
    void CloseClearThread();
	//##ModelId=44CF175602DF
    void AddClearThread(HANDLE hThread);



	//##ModelId=44CF175602EF
    HANDLE CreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, void* pContext, bool bSuspend = false);


	//##ModelId=44CF1756030D
    bool CreateAsyWindow();
	//##ModelId=44CF1756031C
    void DestroyAsyWindow();
	//##ModelId=44CF1756032C
    LRESULT AsyWindowProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam);
	//##ModelId=44CF1756034B
    static LRESULT CALLBACK sAsyWindowProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam);
	//##ModelId=44CF1756035B
    void PostAsyMessage(UINT nMessage, WPARAM wParam, LPARAM lParam)
    {
        PostMessage(m_hAsyWnd, nMessage, wParam, lParam);
    }
	//##ModelId=44CF1756036D
    void SendAsyMessage(UINT nMessage, WPARAM wParam, LPARAM lParam)
    {
        SendMessage(m_hAsyWnd, nMessage, wParam, lParam);
    }

    // do connect.
	//##ModelId=44CF17560371
    DWORD ConnectThreadProc(void*);
	//##ModelId=44CF1756037B
    static DWORD WINAPI sConnectThreadProc(void*);

    // do listen
	//##ModelId=44CF1756038A
    DWORD ListenThreadProc(void*);
	//##ModelId=44CF1756038C
    static DWORD WINAPI sListenThreadProc(void*);

    // do send
	//##ModelId=44CF1756039A
    DWORD SendThreadProc(void*);
	//##ModelId=44CF175603A9
    DWORD SendBlockThreadProc(void*);
	//##ModelId=44CF175603AB
    DWORD SendToThreadProc(void*);
	//##ModelId=44CF175603AD
    static DWORD WINAPI sSendThreadProc(void*);
	//##ModelId=44CF175603B9
    static DWORD WINAPI sSendBlockThreadProc(void*);
	//##ModelId=44CF175603C8
    static DWORD WINAPI sSendToThreadProc(void*);

    // do recv
	//##ModelId=44CF175603D9
    CJoyCriticalSection m_recvLock;
	//##ModelId=44CF175603E0
    CJoySingleList<CJoySockRecvData>    m_recvDatas;

	//##ModelId=44CF17570002
	void JoySaveLog(const char* path, const char* logText);
	//##ModelId=44CF17570005
	void DbPrint(const char* logText);
	//##ModelId=44CF1757000F
    void PostRecvData(CJoySockRecvData* pData);
	//##ModelId=44CF17570011
    CJoySockRecvData* PeekRecvData();
	//##ModelId=44CF17570012
    DWORD RecvThreadProc(void*);
	//##ModelId=44CF1757001F
    DWORD RecvBlockThreadProc(void*);
	//##ModelId=44CF17570021
    DWORD RecvFromThreadProc(void*);
	//##ModelId=44CF17570023
    static DWORD WINAPI sRecvThreadProc(void*);
	//##ModelId=44CF1757002E
    static DWORD WINAPI sRecvBlockThreadProc(void*);
	//##ModelId=44CF17570031
    static DWORD WINAPI sRecvFromThreadProc(void*);

};

extern CJoySocketTool g_sockTool;


#endif  // __SOCKTOOL_H_COMMON_BASE__
